﻿using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.Data.Objects;
using System.Diagnostics;
using TaskManager.Domain.BusinessObjects;
using TaskManager.Domain.Repositories;

namespace TaskManager.DataAccess.Repositories
{
    /// <summary>
    /// Database context
    /// </summary>
    public class TaskManagerDbContext : DbContext, IUnitOfWork
    {
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(TaskManagerDbContext));

        /// <summary>
        /// Constructor
        /// </summary>
        public TaskManagerDbContext()
            : base("TaskManager")
        {
            if (Log.IsDebugEnabled) Log.Debug("Created TaskManagerDbContext");

            ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += OnObjectMaterialized;
        }

        public DbSet<User> Users { get; set; }
        public DbSet<Task> Tasks { get; set; }
        public DbSet<Project> Projects { get; set; }
        public DbSet<Comment> Comments { get; set; }
        public DbSet<ProjectLogEntry> ProjectLogs { get; set; }
        public DbSet<TaskLogEntry> TaskLogs { get; set; }

        public event ObjectMaterializedEventHandler ObjectMaterialized; // Expose ObjectMaterialized event to clients

        public void Save()
        {
            try
            {
                if (Log.IsDebugEnabled) Log.Debug("Saving changes in the database");
                
                SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }

                throw;
            }
        }

        void OnObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
        {
            if(ObjectMaterialized != null)
                ObjectMaterialized(sender, e);
        }
    }
}
